home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / dev / lang / pcq12src.lzh / Source / Optimize.p < prev    next >
Text File  |  1991-04-18  |  10KB  |  355 lines

  1. External;
  2.  
  3. {$I "Pascal.i"}
  4.  
  5.  
  6.     Procedure Error(msg : String);
  7.     External;
  8.  
  9.  
  10. Procedure Optimize(Expr : ExprPtr);
  11. var
  12.     Param : ExprPtr;
  13.  
  14.     Function BinaryOptimize : Boolean;
  15.     begin
  16.     with Expr^ do begin
  17.         Optimize(Left);
  18.         Optimize(Right);
  19.         if (Left^.Kind = Const1) and (Right^.Kind = Const1) then begin
  20.         Kind := Const1;
  21.         BinaryOptimize := True;
  22.         end else
  23.         BinaryOptimize := False;
  24.     end;
  25.     end;
  26.  
  27. begin
  28.     with Expr^ do begin
  29.     if Kind <= xor1 then begin
  30.         if Kind <= or1 then begin
  31.         case Kind of              { From and1 to or1 } 
  32.           and1 : if BinaryOptimize then
  33.                  Value := Left^.Value and Right^.Value
  34.                          else if (Left^.Kind = Const1) and
  35.                                  (Left^.Value = 0) and
  36.                                  ShortCircuit then begin
  37.                              Kind := Const1;
  38.                              Value := 0;
  39.                          end else if (Right^.Kind = Const1) and
  40.                                      (Right^.Value = 0) and
  41.                                      ShortCircuit then begin
  42.                              Kind := Const1;
  43.                              Value := 0;
  44.                          end;
  45.           const1 : ;
  46.           div1 : if BinaryOptimize then begin
  47.                  if Left^.Value <> 0 then
  48.                  Value := Right^.Value div Left^.Value
  49.                  else begin
  50.                  Error("Division by zero in DIV expression");
  51.                  Value := 1;
  52.                  EType := BadType;
  53.                  end;
  54.              end else if (Left^.Kind = Const1) and
  55.                     (Left^.Value = 0) then
  56.                  Error("Division by zero in DIV expression");
  57.           func1: begin
  58.                  Param := Expr^.Left;    
  59.                  while Param <> Nil do begin
  60.                  Optimize(Param);
  61.                  Param := Param^.Next;
  62.                  end;
  63.              end;
  64.           mod1 : if BinaryOptimize then begin
  65.                  if Left^.Value <> 0 then
  66.                  Value := Right^.Value mod Left^.Value
  67.                  else begin
  68.                  Error("Division by zero in MOD expression");
  69.                  Value := 1;
  70.                  EType := BadType;
  71.                  end;
  72.              end else if (Left^.Kind = Const1) and
  73.                     (Left^.Value = 0) then
  74.                 Error("Division by zero in MOD expression");
  75.           not1 : begin
  76.                  Optimize(Left);
  77.                  if Left^.Kind = Const1 then begin
  78.                  Value := not Left^.Value;
  79.                  Kind := Const1;
  80.                  end;
  81.              end;
  82.           or1  : if BinaryOptimize then
  83.                  Value := Left^.Value or Right^.Value
  84.                          else if (Left^.Kind = Const1) and
  85.                                  (Left^.Value = -1) and
  86.                                  ShortCircuit then begin
  87.                              Value := -1;
  88.                              Kind := Const1;
  89.                          end else if (Right^.Kind = Const1) and
  90.                                      (Right^.Value = -1) and
  91.                                      ShortCircuit then begin
  92.                              Value := -1;
  93.                              Kind := Const1;
  94.                          end;
  95.         else
  96.             Writeln(OutFile, '1:Did not optimize ', Ord(Kind));
  97.         end;
  98.         end else begin
  99.         case Kind of        { from shl1 to xor1 }
  100.           shl1 : if BinaryOptimize then
  101.                  Value := Left^.Value shl Right^.Value
  102.              else if Right^.Kind = Const1 then begin
  103.                  if (Right^.Value) and 31 = 0 then
  104.                  Expr^ := Left^;
  105.              end;
  106.           shr1 : if BinaryOptimize then
  107.                  Value := Left^.Value shr Right^.Value
  108.              else if Right^.Kind = Const1 then begin
  109.                  if (Right^.Value) and 31 = 0 then
  110.                  Expr^ := Left^;
  111.              end;
  112.           type1: Optimize(Left);
  113.           var1 : ;
  114.           xor1 : if BinaryOptimize then
  115.                  Value := Left^.Value xor Right^.Value;
  116.         else
  117.             Writeln(OutFile, '2:Did not optimize ', Ord(Kind));
  118.         end;
  119.         end;
  120.     end else begin
  121.         if Kind <= minus1 then begin
  122.         case Kind of
  123.           numeral1 : ;
  124.           asterisk1 :
  125.             if BinaryOptimize then begin
  126.                 if EType = RealType then
  127.                 Value := Integer(Real(Left^.Value) *
  128.                         Real(Right^.Value))
  129.                 else
  130.                 Value := Left^.Value * Right^.Value;
  131.             end else if Left^.Kind = Const1 then begin
  132.                 if Left^.Value = 0 then begin { zero for anything }
  133.                 Value := 0;
  134.                 Kind := Const1;
  135.                 end else if (EType^.Object = ob_ordinal) and
  136.                     (Left^.Value = 1) then begin
  137.                 if Right^.EType^.Size < 4 then begin
  138.                     Kind := Short2Long;
  139.                     Left := Right;
  140.                     Right := Nil;
  141.                 end else
  142.                     Expr^ := Right^;
  143.                 end;
  144.             end;
  145.           equal1 :
  146.             if BinaryOptimize then begin
  147.                 if Left^.EType = RealType then
  148.                 Value := Ord(Real(Left^.Value) =
  149.                         Real(Right^.Value))
  150.                 else
  151.                 Value := Ord(Left^.Value = Right^.Value);
  152.             end;
  153.           greater1 :
  154.             if BinaryOptimize then begin
  155.                 if Left^.EType = RealType then
  156.                 Value := Ord(Real(Left^.Value) >
  157.                         Real(Right^.Value))
  158.                 else
  159.                 Value := Ord(Left^.Value > Right^.Value);
  160.             end;
  161.           leftbrack1 :
  162.             begin
  163.                 Optimize(Right);
  164.                 if (Right^.Kind = Const1) and
  165.                 (Left^.EType^.Object = ob_array) then begin
  166.                 if RangeCheck then begin
  167.                     if (Right^.Value < Left^.EType^.Lower) or
  168.                        (Right^.Value > Left^.EType^.Upper) then
  169.                     Error("Index out of range");
  170.                 end;
  171.                 Kind := Period1;
  172.                 Value := Right^.Value;
  173.                 end;
  174.             end;
  175.           less1 :
  176.             if BinaryOptimize then begin
  177.                 if Left^.EType = RealType then
  178.                 Value := Ord(Real(Left^.Value) <
  179.                         Real(Right^.Value))
  180.                 else
  181.                 Value := Ord(Left^.Value < Right^.Value);
  182.             end;
  183.           minus1 :
  184.             if Right = Nil then begin { Unary minus }
  185.                 Optimize(Left);
  186.                 if Left^.Kind = Const1 then begin
  187.                 if EType = RealType then
  188.                     Value := Integer(-Real(Left^.Value))
  189.                 else
  190.                     Value := -Left^.Value;
  191.                 Kind := Const1;
  192.                 if EType = ByteType then
  193.                     EType := ShortType;
  194.                 end;
  195.             end else if BinaryOptimize then begin
  196.                 if EType = RealType then
  197.                 Value := Integer(Real(Right^.Value) -
  198.                         Real(Left^.Value))
  199.                 else
  200.                 Value := Right^.Value - Left^.Value;
  201.             end else if Left^.Kind = Const1 then begin
  202.                 if Left^.Value = 0 then
  203.                 Expr^ := Right^;
  204.             end;
  205.         else
  206.             Writeln(OutFile,'3:Did not optimize ', Ord(Kind));
  207.         end;
  208.         end else if Kind <= realnumeral1 then begin
  209.         case Kind of { notequal1 through realnumeral1 }
  210.           notequal1 :
  211.             if BinaryOptimize then begin
  212.                 if Left^.EType = RealType then
  213.                 Value := Ord(Real(Left^.Value) <>
  214.                         Real(Right^.Value))
  215.                 else
  216.                 Value := Ord(Left^.Value <> Right^.Value);
  217.             end;
  218.           notgreater1 :
  219.             if BinaryOptimize then begin
  220.                 if Left^.EType = RealType then
  221.                 Value := Ord(Real(Left^.Value) <=
  222.                         Real(Right^.Value))
  223.                 else
  224.                 Value := Ord(Left^.Value <= Right^.Value);
  225.             end;
  226.           notless1 :
  227.             if BinaryOptimize then begin
  228.                 if Left^.EType = RealType then
  229.                 Value := Ord(Real(Left^.Value) >=
  230.                         Real(Right^.Value))
  231.                 else
  232.                 Value := Ord(Left^.Value >= Right^.Value);
  233.             end;
  234.           period1 : Optimize(Left);
  235.           plus1 :
  236.             if BinaryOptimize then begin
  237.                 if EType = RealType then
  238.                 Value := Integer(Real(Left^.Value) +
  239.                         Real(Right^.Value))
  240.                 else
  241.                 Value := Left^.Value + Right^.Value;
  242.             end else if Left^.Kind = Const1 then begin
  243.                 if Left^.Value = 0 then
  244.                 Expr^ := Right^;
  245.             end;
  246.           quote1 : ;
  247.           carat1 : begin
  248.                 Optimize(Left);
  249.                 if Right <> Nil then
  250.                     Optimize(Right);
  251.                end;
  252.           at1 : Optimize(Left);
  253.           realdiv1 :
  254.             if BinaryOptimize then begin
  255.                 if Left^.Value <> 0 then
  256.                 Value := Integer(Real(Right^.Value) /
  257.                         Real(Left^.Value))
  258.                 else begin
  259.                 Error("Division by zero in '/' expression");
  260.                 Value := 1;
  261.                 EType := BadType;
  262.                 end;
  263.             end;
  264.           realnumeral1 : ;
  265.         else
  266.             Writeln(OutFile, '4:Did not optimize ', Ord(Kind));
  267.         end;
  268.         end else begin
  269.         case Kind of        { int2real1 through field1 }
  270.           int2real :
  271.             begin
  272.                 Optimize(Left);
  273.                 if Left^.Kind = Const1 then begin
  274.                 Value := Integer(Float(Left^.Value));
  275.                 Kind := Const1;
  276.                 end;
  277.             end;
  278.           real2int :
  279.             begin
  280.                 Optimize(Left);
  281.                 if Left^.Kind = Const1 then begin
  282.                 Value := Trunc(Real(Left^.Value));
  283.                 Kind := Const1;
  284.                 end;
  285.             end;
  286.           short2long :
  287.             begin
  288.                 Optimize(Left);
  289.                 if Left^.Kind = Const1 then begin
  290.                 Value := Left^.Value;
  291.                 Kind := Const1;
  292.                 end else if Left^.Kind = byte2short then begin
  293.                 Kind := byte2long;
  294.                 Left := Left^.Left;
  295.                 end;
  296.             end;
  297.           byte2short :
  298.             begin
  299.                 Optimize(Left);
  300.                 if Left^.EType^.Size > 1 then
  301.                 Expr^ := Left^
  302.                 else if Left^.Kind = Const1 then begin
  303.                 Kind := Const1;
  304.                 Value := Left^.Value and 255;
  305.                 end;
  306.             end;
  307.           byte2long : ;
  308.           stanfunc1 :
  309.             if (Value < 7) or (Value > 9) then begin
  310.                 Optimize(Left);
  311.                 if Left^.Kind = Const1 then begin
  312.                 if (Value < 15) or (Value > 16) then begin
  313.                     case Value of
  314.                       1,2 : Value := Left^.Value;
  315.                       3 : Value := Ord(Odd(Left^.Value));
  316.                       4 : if EType = RealType then
  317.                           Value := Integer(Abs(Real(Left^.Value)))
  318.                       else
  319.                           Value := Abs(Left^.Value);
  320.                       5 : Value := Succ(Left^.Value);
  321.                       6 : Value := Pred(Left^.Value);
  322.                       10: Value := Trunc(Real(Left^.Value));
  323.                       11: Value := Round(Real(Left^.Value));
  324.                       12: Value := Integer(Float(Left^.Value));
  325.                       13: Value := Integer(Floor(Real(Left^.Value)));
  326.                       14: Value := Integer(Ceil(Real(Left^.Value)));
  327.                       17: Value := Bit(Left^.Value);
  328.                       18: Value := Integer(Sqr(Real(Left^.Value)));
  329.                       19: Value := Integer(Sin(Real(Left^.Value)));
  330.                       20: Value := Integer(Cos(Real(Left^.Value)));
  331.                       21: Value := Integer(Sqrt(Real(Left^.Value)));
  332.                       22: Value := Integer(Tan(Real(Left^.Value)));
  333.                       23: Value := Integer(ArcTan(Real(Left^.Value)));
  334.                       24: Value := Integer(Ln(Real(Left^.Value)));
  335.                       25: Value := Integer(Exp(Real(Left^.Value)));
  336.                     end;
  337.                     Kind := Const1;
  338.                 end;
  339.                 end;
  340.             end else if (Value = 7) or (Value = 8) then begin
  341.                 Optimize(Left^.Next);    { Record size }
  342.                 Optimize(Left);        { File expression }
  343.                 Optimize(Right);        { Filename }
  344.             end;
  345.           field1 : ;
  346.         else
  347.             Writeln(OutFIle, '5:Did not optimize ', Ord(Kind));
  348.         end;
  349.         end;
  350.     end; { else }
  351.     if (Kind = Const1) and (EType = ByteType) and (Value < 0) then
  352.         EType := ShortType;
  353.     end; { with }
  354. end; { Optimize }
  355.